package com.cloudkinto.common.utils;

import com.alibaba.fastjson.JSON;
import okhttp3.*;

import java.io.File;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Proxy;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.concurrent.TimeUnit;


/**
 * @author fanp
 * @version v1.0.0
 * @Description :
 * @Create on : 2021/11/15 10:26
 **/
public class WowmaUtil {

    /**
     * SP-API 通用GET方法
     *
     * @param serviceUrl
     * @param parametersMap
     * @return
     * @throws Exception
     */
    public static String raAPidoGet(String serviceUrl, String token, Map<String, Object> parametersMap) throws Exception {
        Map<String, String> headerMap = new HashMap<>();
        headerMap.put("Authorization", "Bearer " + token);
        headerMap.put("content-type", "application/x-www-form-urlencoded");
        if (parametersMap.size() > 0)
            serviceUrl = serviceUrl + "?" + sortParams(parametersMap);
        InetSocketAddress addr = new InetSocketAddress("127.0.0.1", 1081);
        Proxy proxy = new Proxy(Proxy.Type.HTTP, addr); // http 代理
        OkHttpClient.Builder builder = OkHttpUtils.getUnsafeOkHttpClient().newBuilder();
        builder.connectTimeout(60, TimeUnit.SECONDS)
                .readTimeout(60, TimeUnit.SECONDS)
                .writeTimeout(60, TimeUnit.SECONDS)
//                .proxy(proxy)
                .retryOnConnectionFailure(false);
        Request.Builder requestBuilder = createSPHeader(headerMap);
        Request request = requestBuilder.url(serviceUrl).get().build();
        Response response = null;
        String body = "";
        response = builder.build().newCall(request).execute();
        body = response.body().string();
//        System.out.println(body);
        return body;
    }

    public static String getBase64ESA(String secret,String license){
        byte[] pass = (secret.trim() + ":" + license.trim()).getBytes(StandardCharsets.UTF_8);
        return "ESA " + Base64.getEncoder().encodeToString(pass);
    }

    public static ResponseBody raAPidoGetResponseBody(String serviceUrl, String secret, String license, Map parametersMap) throws Exception {
        Map<String, String> headerMap = new HashMap<>();
        headerMap.put("Authorization", getBase64ESA(secret,license));
        headerMap.put("content-type", "application/json; charset=utf-8");
        if (parametersMap.size() > 0)
            serviceUrl = serviceUrl + "?" + sortParams(parametersMap);
        InetSocketAddress addr = new InetSocketAddress("127.0.0.1", 1081);
        Proxy proxy = new Proxy(Proxy.Type.HTTP, addr); // http 代理
        OkHttpClient.Builder builder = OkHttpUtils.getUnsafeOkHttpClient().newBuilder();
        builder.connectTimeout(60, TimeUnit.SECONDS)
                .readTimeout(60, TimeUnit.SECONDS)
                .writeTimeout(60, TimeUnit.SECONDS)
//                .proxy(proxy)
                .retryOnConnectionFailure(false);
        Request.Builder requestBuilder = createSPHeader(headerMap);
        Request request = requestBuilder.url(serviceUrl).get().build();
        Response response = null;
//        byte[] in = null;
        response = builder.build().newCall(request).execute();
//        in = response.body().bytes();
        return response.body();
    }

    /**
     * @param serviceUrl    接口地址
     * @return
     * @throws Exception
     */
    public static String raAPidoPOST(String serviceUrl, String token, Object param) {
        Map<String, String> headerMap = new HashMap<>();
        headerMap.put("Authorization", "Bearer " + token);
        headerMap.put("content-type", "application/xml; charset=utf-8");
        OkHttpClient client = OkHttpUtils.getUnsafeOkHttpClient();
        InetSocketAddress addr = new InetSocketAddress("127.0.0.1", 1081);
        Proxy proxy = new Proxy(Proxy.Type.HTTP, addr); // http 代理
        OkHttpClient.Builder builder = client.newBuilder();
        builder.connectTimeout(60, TimeUnit.SECONDS)
                .readTimeout(60, TimeUnit.SECONDS)
                .writeTimeout(60, TimeUnit.SECONDS)
//                .proxy(proxy)
                .retryOnConnectionFailure(false);
        Request.Builder requestBuilder = createSPHeader(headerMap);
        Request request = requestBuilder.url(serviceUrl)
                .post(RequestBody.create(Objects.requireNonNull(MediaType.parse("application/json")), JSON.toJSONString(param)))
                .build();
        Response response = null;
        String body = "";
        try {
            response = builder.build().newCall(request).execute();
            body = response.body().string();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return body;

    }


    /**
     * @param serviceUrl    接口地址
     * @param parametersMap body参数
     * @return
     * @throws Exception
     */
    public static String raAPidoPUT(String serviceUrl, String secret, String license, Map parametersMap) throws Exception {
        Map<String, String> headerMap = new HashMap<>();
        headerMap.put("Authorization", getBase64ESA(secret,license));
        headerMap.put("Content-type", "application/json; charset=utf-8");
        OkHttpClient client = OkHttpUtils.getUnsafeOkHttpClient();
        InetSocketAddress addr = new InetSocketAddress("127.0.0.1", 1082);
        Proxy proxy = new Proxy(Proxy.Type.HTTP, addr); // http 代理
        OkHttpClient.Builder builder = client.newBuilder();
        builder.connectTimeout(60, TimeUnit.SECONDS)
                .readTimeout(60, TimeUnit.SECONDS)
                .writeTimeout(60, TimeUnit.SECONDS)
//                .proxy(proxy)
                .retryOnConnectionFailure(false);
        Request.Builder requestBuilder = createSPHeader(headerMap);
        Request request = requestBuilder.url(serviceUrl)
                .put(RequestBody.create(MediaType.parse("application/json"), JSON.toJSONString(parametersMap)))
                .build();
        System.out.println("requestBody:" + JSON.toJSONString(parametersMap));
        Response response = null;
        String body = "";
        response = client.newCall(request).execute();
        body = response.body().string();
//        System.out.println(body);
        return body;
    }


    /**
     * @param serviceUrl    接口地址
     * @param parametersMap body参数
     * @return
     * @throws Exception
     */
    public static String raAPidoPATCH(String serviceUrl, String secret, String license, Map parametersMap) throws Exception {
        Map<String, String> headerMap = new HashMap<>();
        headerMap.put("Authorization", getBase64ESA(secret,license));
        headerMap.put("content-type", "application/json; charset=utf-8");
        OkHttpClient client = OkHttpUtils.getUnsafeOkHttpClient();
        InetSocketAddress addr = new InetSocketAddress("127.0.0.1", 1082);
        Proxy proxy = new Proxy(Proxy.Type.HTTP, addr); // http 代理
        OkHttpClient.Builder builder = client.newBuilder();
        builder.connectTimeout(60, TimeUnit.SECONDS)
                .readTimeout(60, TimeUnit.SECONDS)
                .writeTimeout(60, TimeUnit.SECONDS)
//                .proxy(proxy)
                .retryOnConnectionFailure(false);
        Request.Builder requestBuilder = createSPHeader(headerMap);
        Request request = requestBuilder.url(serviceUrl)
                .patch(RequestBody.create(MediaType.parse("application/json"), JSON.toJSONString(parametersMap)))
                .build();
        System.out.println("requestBody:" + JSON.toJSONString(parametersMap));
        Response response = null;
        String body = "";
        response = client.newCall(request).execute();
        body = response.body().string();
//        System.out.println(body);
        return body;
    }


    /**
     * @param serviceUrl    接口地址
     * @return
     * @throws Exception
     */
    public static String raAPidoPOSTFile(String serviceUrl, String secret, String license, File file) throws Exception {
        Map<String, String> headerMap = new HashMap<>();
        headerMap.put("Authorization", getBase64ESA(secret,license));
        headerMap.put("content-type", "application/json; charset=utf-8");
        OkHttpClient client = OkHttpUtils.getUnsafeOkHttpClient();
        InetSocketAddress addr = new InetSocketAddress("127.0.0.1", 1082);
        Proxy proxy = new Proxy(Proxy.Type.HTTP, addr); // http 代理
        OkHttpClient.Builder builder = client.newBuilder();
        builder.connectTimeout(60, TimeUnit.SECONDS)
                .readTimeout(60, TimeUnit.SECONDS)
                .writeTimeout(60, TimeUnit.SECONDS)
//                .proxy(proxy)
                .retryOnConnectionFailure(false);
        Request.Builder requestBuilder = createSPHeader(headerMap);

        RequestBody fileBody = RequestBody.create(MediaType.parse("image/png"), file);
        RequestBody requestBody = new MultipartBody.Builder()
                .setType(MultipartBody.FORM)
                .addPart(
                        Headers.of("Content-Disposition", "form-data; name=\"file\"; filename=\"" +URLEncoder.encode(file.getName(),"UTF-8") + "\""),
                        RequestBody.create(MediaType.parse("image/png"), file))
//                .addPart(
//                        Headers.of("Content-Disposition", "form-data; name=\"imagetype\""),
//                        RequestBody.create(null, imageType))
//                .addPart(
//                        Headers.of("Content-Disposition", "form-data; name=\"userphone\""),
//                        RequestBody.create(null, userPhone))

//                .addFormDataPart("file", file.getName(), fileBody)
                .build();

        Request request = requestBuilder.url(serviceUrl)
                .post(requestBody)
                .build();
        Response response = null;
        String body = "";
        response = client.newCall(request).execute();
        body = response.body().string();
//        System.out.println(body);
        return body;

    }


    public static String raAPidoPOSTXml(String serviceUrl, String token, String contentType, String param) throws Exception {
        Map<String, String> headerMap = new HashMap<>();
        headerMap.put("Authorization", "Bearer " + token);
//        headerMap.put("content-type", "text/xml; charset=UTF-8");
        headerMap.put("content-type", contentType);
        OkHttpClient client = OkHttpUtils.getUnsafeOkHttpClient();
        InetSocketAddress addr = new InetSocketAddress("127.0.0.1", 1081);
        Proxy proxy = new Proxy(Proxy.Type.HTTP, addr); // http 代理
        OkHttpClient.Builder builder = client.newBuilder();
        builder.connectTimeout(60, TimeUnit.SECONDS)
                .readTimeout(60, TimeUnit.SECONDS)
                .writeTimeout(60, TimeUnit.SECONDS)
//                .proxy(proxy)
                .retryOnConnectionFailure(false);
        Request.Builder requestBuilder = createSPHeader(headerMap);
        Request request = requestBuilder.url(serviceUrl)
                .post(RequestBody.create(MediaType.parse(contentType),param))
                .build();
        System.out.println("requestBody:" + JSON.toJSONString(param));
        Response response = null;
        String body = "";
//        response = client.newCall(request).execute();
        response = builder.build().newCall(request).execute();
        body = response.body().string();
//        System.out.println(body);
        return body;

    }


    public static String raAPidoPOSTFile(String serviceUrl, String secret, String license, File file, String xmlStr) throws Exception {
        Map<String, String> headerMap = new HashMap<>();
        headerMap.put("Authorization", getBase64ESA(secret,license));
        headerMap.put("content-type", "multipart/form-data");
        OkHttpClient client = OkHttpUtils.getUnsafeOkHttpClient();
        InetSocketAddress addr = new InetSocketAddress("127.0.0.1", 1082);
        Proxy proxy = new Proxy(Proxy.Type.HTTP, addr); // http 代理
        OkHttpClient.Builder builder = client.newBuilder();
        builder.connectTimeout(60, TimeUnit.SECONDS)
                .readTimeout(60, TimeUnit.SECONDS)
                .writeTimeout(60, TimeUnit.SECONDS)
//                .proxy(proxy)
                .retryOnConnectionFailure(false);
        Request.Builder requestBuilder = createSPHeader(headerMap);

        RequestBody requestBody = new MultipartBody.Builder()
                .setType(MultipartBody.FORM)
                .addPart(
                        Headers.of("Content-Disposition", "form-data; name=\"xml\""),
                        RequestBody.create(MediaType.parse("text/xml; charset=UTF-8"), xmlStr))
                .addPart(
                        Headers.of("Content-Disposition", "form-data; name=\"file\"; filename=\"" +URLEncoder.encode(file.getName(),"UTF-8") + "\""),
                        RequestBody.create(MediaType.parse("image/jpg"), file))
                .build();

        Request request = requestBuilder.url(serviceUrl)
                .post(requestBody)
                .build();
        Response response = null;
        String body = "";
        response = client.newCall(request).execute();
        body = response.body().string();
//        System.out.println(body);
        return body;

    }



    public static String raAPidoPOSTFile(String serviceUrl, String secret, String license, String xmlStr) throws Exception {
        Map<String, String> headerMap = new HashMap<>();
        headerMap.put("Authorization", getBase64ESA(secret,license));
        headerMap.put("content-type", "multipart/form-data");
        OkHttpClient client = OkHttpUtils.getUnsafeOkHttpClient();
        InetSocketAddress addr = new InetSocketAddress("127.0.0.1", 1082);
        Proxy proxy = new Proxy(Proxy.Type.HTTP, addr); // http 代理
        OkHttpClient.Builder builder = client.newBuilder();
        builder.connectTimeout(60, TimeUnit.SECONDS)
                .readTimeout(60, TimeUnit.SECONDS)
                .writeTimeout(60, TimeUnit.SECONDS)
//                .proxy(proxy)
                .retryOnConnectionFailure(false);
        Request.Builder requestBuilder = createSPHeader(headerMap);

        RequestBody requestBody = new MultipartBody.Builder()
                .setType(MultipartBody.FORM)
                .addPart(
                        Headers.of("Content-Disposition", "form-data; name=\"xml\""),
                        RequestBody.create(MediaType.parse("text/xml; charset=UTF-8"), xmlStr))
                .build();

        Request request = requestBuilder.url(serviceUrl)
                .post(requestBody)
                .build();
        Response response = null;
        String body = "";
        response = client.newCall(request).execute();
        body = response.body().string();
//        System.out.println(body);
        return body;

    }

/**
 * ====================================================加密参数构建====================================================================
 */
    /**
     * 构建header参数
     *
     * @param headerMap
     * @return
     */
    public static Request.Builder createSPHeader(Map<String, String> headerMap) {
        Request.Builder requestBuilder = new Request.Builder();
        Iterator<Map.Entry<String, String>> pairs =
                headerMap.entrySet().iterator();
        while (pairs.hasNext()) {
            Map.Entry<String, String> data = pairs.next();
            requestBuilder.addHeader(data.getKey(), data.getValue());
        }
        return requestBuilder;
    }

    /**
     * 1.1 对传递参数转换(Body)
     *
     * @param parameters
     * @return
     */
    public static String sortParams(Map<String, Object> parameters) {
        StringBuilder data = new StringBuilder();
        if (parameters == null) return "";
        Map<String, Object> sorted = new TreeMap<String, Object>();
        sorted.putAll(parameters);
        Iterator<Map.Entry<String, Object>> pairs =
                sorted.entrySet().iterator();
        while (pairs.hasNext()) {
            Map.Entry<String, Object> pair = pairs.next();
            if (pair.getValue() != null) {
                data.append(URLEncoder.encode(pair.getKey()) + "=" + URLEncoder.encode(pair.getValue().toString()));
            } else {
                data.append(URLEncoder.encode(pair.getKey()) + "=");
            }
            if (pairs.hasNext()) {
                data.append("&");
            }
        }
//        System.out.println("参数转换(Body)\n" + data.toString());
        return data.toString();
    }

    /**
     * 二进制值转换为十六进制
     *
     * @param bytes
     * @return
     */
    private static String byteToHex(byte[] bytes) {
        StringBuffer result = new StringBuffer();
        for (int i = 0; i < bytes.length; i++) {
            if ((bytes[i] & 0xff) < 0x10)
                result.append("0");
            result.append(Long.toString(bytes[i] & 0xff, 16));
        }
        return result.toString().toLowerCase();
    }
}
